package cn.core.conf.service;

import cn.core.conf.eo.Conf;
import cn.core.conf.mapper.ConfMapper;
import cn.core.conf.qo.ConfQO;
import cn.core.conf.vo.ConfVO;
import cn.core.tool.ao.DataExportAO;
import cn.core.tool.context.CoreContextData;
import cn.core.tool.event.CoreDataEvent;
import cn.core.tool.exception.CoreException;
import cn.core.tool.service.FileService;
import cn.core.tool.util.CoreTool;
import cn.core.tool.util.Paging;
import cn.core.tool.util.Param;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.google.gson.reflect.TypeToken;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 系统配置 服务
 */
@Log4j2
@Service
public class ConfService {

  @Resource
  private ApplicationEventPublisher applicationEventPublisher;

  @Resource
  private FileService fileService;

  @Resource
  private ConfMapper confMapper;

  @Value("${spring.profiles.active}")
  private String confEnv;

  /**
   * 系统配置 >>> 保存
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public Conf save(Conf eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      eo.setId(CoreTool.getUUID32());
      confMapper.save(eo);
      return eo;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 批量保存
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public Collection<Conf> saveBatch(Collection<Conf> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (Conf eo : eos) {
        if (CoreTool.isNullEo(eo)) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        eo.setId(CoreTool.getUUID32());
      }
      confMapper.saveBatch(new Paging<>(), eos);
      return eos;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 修改
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public Conf update(Conf eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      Conf oeo = confMapper.pk(new ConfQO().setId(eo.getId()));
      if (CoreTool.isNullEo(oeo)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
//      if (eo.getVersions() != null ? !eo.getVersions().equals(oeo.getVersions()) : oeo.getVersions() != null ? true : false) {
//        throw new CoreException(CoreException.E_VERSIONS_ERR);
//      }
      confMapper.update(eo);
      return eo;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 批量修改
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public Collection<Conf> updateBatch(Collection<Conf> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (Conf eo : eos) {
        if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
        Conf oeo = confMapper.pk(new ConfQO().setId(eo.getId()));
        if (CoreTool.isNullEo(oeo)) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
//        if (eo.getVersions() != null ? !eo.getVersions().equals(oeo.getVersions()) : oeo.getVersions() != null ? true : false) {
//          throw new CoreException(CoreException.E_VERSIONS_ERR);
//        }
      }
      confMapper.updateBatch(new Paging<>(), eos);
      return eos;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 删除
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public void remove(Conf eo) throws Exception {
    try {
      if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      confMapper.remove(eo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 批量删除
   */
  @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
  public void removeBatch(Collection<Conf> eos) throws Exception {
    try {
      if (CoreTool.isEmpty(eos)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      for (Conf eo : eos) {
        if (CoreTool.isNullEo(eo) || CoreTool.isNullStr(eo.getId())) {
          throw new CoreException(CoreException.E_PARAM_ERR);
        }
      }
      confMapper.removeBatch(eos);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 数据量
   */
  public Long count(ConfQO qo) throws Exception {
    try {
      return confMapper.count(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 主键查询
   */
  public Conf pk(ConfQO qo) throws Exception {
    try {
      if (CoreTool.isNullEo(qo) || CoreTool.isNullStr(qo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      return confMapper.pk(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 查询
   */
  public Collection<Conf> query(ConfQO qo) throws Exception {
    try {
      return confMapper.query(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 分页
   */
  public Paging<Conf> paging(Param<ConfQO> param) throws Exception {
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      if (param.getPage() < 1 || param.getRows() < 1) {
        throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
      }
      Paging<Conf> paging = new Paging<>(param);
      if (CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        Long count = confMapper.count(null);
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(confMapper.paging(paging, null));
        }
      } else {
        Long count = confMapper.count(param.get());
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(confMapper.paging(paging, param.get()));
        }
      }
      return paging;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 业务数据量
   */
  public Long countVo(ConfQO qo) throws Exception {
    try {
      return confMapper.countVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 业务主键查询
   */
  public ConfVO pkVo(ConfQO qo) throws Exception {
    try {
      if (CoreTool.isNullEo(qo) || CoreTool.isNullStr(qo.getId())) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      return confMapper.pkVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 业务查询
   */
  public Collection<ConfVO> queryVo(ConfQO qo) throws Exception {
    try {
      return confMapper.queryVo(qo);
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 业务分页
   */
  public Paging<ConfVO> pagingVo(Param<ConfQO> param) throws Exception {
    try {
      if (CoreTool.isNullEo(param)) {
        throw new CoreException(CoreException.E_PARAM_ERR);
      }
      if (param.getPage() < 1 || param.getRows() < 1) {
        throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
      }
      Paging<ConfVO> paging = new Paging<>(param);
      if (CoreTool.isEmpty(param.getData()) || CoreTool.isNullEo(param.get())) {
        Long count = confMapper.countVo(null);
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(confMapper.pagingVo(paging, null));
        }
      } else {
        Long count = confMapper.countVo(param.get());
        paging.setCount(count);
        if (count > 0) {
          if (count <= paging.getOffset()) {
            throw new CoreException(CoreException.E_PAGING_PARAM_ERR);
          }
          paging.setData(confMapper.pagingVo(paging, param.get()));
        }
      }
      return paging;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 数据导入
   */
  public Collection<Conf> dataImport(String ao) throws Exception {
    try {
      if (CoreTool.isNullStr(ao)) {
        throw new CoreException(CoreException.E_DATA_IMPORT_FILE_URL_IS_NULL_ERR);
      }
      List<Conf> allData = null;
      try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(fileService.getFileStreamByFileUrl(ao))) {
        ExcelReader reader = ExcelUtil.getReader(byteArrayInputStream);
        reader.addHeaderAlias("配置标识", "confKey");
        reader.addHeaderAlias("配置名称", "confName");
        reader.addHeaderAlias("配置类型", "confType");
        reader.addHeaderAlias("配置环境", "confEnv");
        reader.addHeaderAlias("配置值", "confValue");
        allData = reader.readAll(Conf.class);
        if (CoreTool.isEmpty(allData)) {
          throw new CoreException(CoreException.E_IMPORT_DATA_IS_NULL_ERR);
        }
        CoreDataEvent confTypeCoreDataEvent = new CoreDataEvent("getDictNameValueMapInfoByDictKey", "confConfType");
        applicationEventPublisher.publishEvent(confTypeCoreDataEvent);
        LinkedHashMap<String, String> confTypeDictNameValueMapInfo = CoreTool.isNotNullStr(confTypeCoreDataEvent.getData()) ? confTypeCoreDataEvent.getData(new TypeToken<LinkedHashMap<String, String>>(){}) : new LinkedHashMap<String, String>();
        CoreDataEvent confEnvCoreDataEvent = new CoreDataEvent("getDictNameValueMapInfoByDictKey", "confConfEnv");
        applicationEventPublisher.publishEvent(confEnvCoreDataEvent);
        LinkedHashMap<String, String> confEnvDictNameValueMapInfo = CoreTool.isNotNullStr(confEnvCoreDataEvent.getData()) ? confEnvCoreDataEvent.getData(new TypeToken<LinkedHashMap<String, String>>(){}) : new LinkedHashMap<String, String>();
        for (Conf eo : allData) {
          eo.setId(CoreTool.getUUID32());
          eo.setConfType(confTypeDictNameValueMapInfo.get(eo.getConfType()));
          eo.setConfEnv(confEnvDictNameValueMapInfo.get(eo.getConfEnv()));
        }
        confMapper.saveBatch(new Paging<>(), allData);
      } catch (IOException e) {
        throw new CoreException(CoreException.E_ERR);
      }
      return allData;
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 数据导出
   */
  public String dataExport(DataExportAO<ConfQO> ao) throws Exception {
    try {
      if (CoreTool.isEmpty(ao.getDataExportFieldConf())) {
        throw new CoreException(CoreException.E_DATA_EXPORT_FIELD_CONF_IS_NULL_ERR);
      }
      Collection<ConfVO> vos = confMapper.queryVo(ao.get());
      if (CoreTool.isEmpty(vos)) {
        throw new CoreException(CoreException.E_EXPORT_DATA_IS_NULL_ERR);
      }
      CoreDataEvent confTypeCoreDataEvent = new CoreDataEvent("getDictValueMapInfoByDictKey", "confConfType");
      applicationEventPublisher.publishEvent(confTypeCoreDataEvent);
      LinkedHashMap<String, String> confTypeDictValueMapInfo = CoreTool.isNotNullStr(confTypeCoreDataEvent.getData()) ? confTypeCoreDataEvent.getData(new TypeToken<LinkedHashMap<String, String>>(){}) : new LinkedHashMap<String, String>();
      CoreDataEvent confEnvCoreDataEvent = new CoreDataEvent("getDictValueMapInfoByDictKey", "confConfEnv");
      applicationEventPublisher.publishEvent(confEnvCoreDataEvent);
      LinkedHashMap<String, String> confEnvDictValueMapInfo = CoreTool.isNotNullStr(confEnvCoreDataEvent.getData()) ? confEnvCoreDataEvent.getData(new TypeToken<LinkedHashMap<String, String>>(){}) : new LinkedHashMap<String, String>();
      for (ConfVO eo : vos) {
        eo.setConfType(confTypeDictValueMapInfo.get(eo.getConfType()));
        eo.setConfEnv(confEnvDictValueMapInfo.get(eo.getConfEnv()));
      }
      return fileService.getFileUrlByDataExportAO(new DataExportAO<ConfVO>()
          .setBigDataExport(ao.getBigDataExport())
          .setFileModule(ao.getFileModule())
          .setFileName(ao.getFileName())
          .setDataExportFieldConf(ao.getDataExportFieldConf())
          .setData(vos));
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

  /**
   * 系统配置 >>> 通过配置标识获取配置值
   */
  public Conf getValueByConfKey(ConfQO qo) throws Exception {
    try {
      if (CoreTool.isNullEo(qo) || CoreTool.isNullStr(qo.getConfKey())) {
        throw new CoreException("配置标识为空！");
      }
      if (CoreContextData.getCurrentContextData() != null && CoreTool.isNotNullStr(CoreContextData.getCurrentContextData().getOrgId())) {
        Collection<Conf> rOrgConfSet = confMapper.query(new ConfQO().setConfEnv(confEnv).setConfKey(qo.getConfKey() + CoreContextData.getCurrentContextData().getOrgId()));
        if (CoreTool.isEmpty(rOrgConfSet)) {
          Collection<Conf> rConfSet = confMapper.query(new ConfQO().setConfEnv(confEnv).setConfKey(qo.getConfKey()));
          if (CoreTool.isEmpty(rConfSet)) {
            throw new CoreException("未找到配置信息！");
          }
          return rConfSet.iterator().next();
        } else {
          return rOrgConfSet.iterator().next();
        }
      } else {
        Collection<Conf> rConfSet = confMapper.query(new ConfQO().setConfEnv(confEnv).setConfKey(qo.getConfKey()));
        if (CoreTool.isEmpty(rConfSet)) {
          throw new CoreException("未找到配置信息！");
        }
        return rConfSet.iterator().next();
      }
    } catch (Exception e) {
      if (log.isDebugEnabled()) {
        log.error(e.getMessage(), e);
      }
      throw e;
    }
  }

}
